﻿using System;
using System.Web;
using System.Text;
using System.Globalization;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace RealDolmen.SharePoint.Helpers
{
    public class SPParser
    {
        public class SPUrlPrefixConstants
        {
            public static string SiteCollection = "~sitecollection";
            public static string Site = "~site";
            public static string List = "~list";
        }

        #region GetUrlPrefix
        public static string GetPrefixedUrl(SPWeb web, SPList list)
        {
            SPWeb parentWeb = list.ParentWeb;

            if (web.ID == parentWeb.ID)
                return GetWebPrefixedUrl(list);
            else
                return SPParser.GetPrefixedUrl(web,list.DefaultView.ServerRelativeUrl);
        }
        public static string GetPrefixedUrl(SPWeb web, string url)
        {
            SPSite site = web.Site;

            if (url.StartsWith("http"))
            {
                string siteUrl = site.Url;
                int idx = siteUrl.IndexOf(site.ServerRelativeUrl);
                string serverUrl = siteUrl.Remove(idx);

                if (url.StartsWith(serverUrl))
                    url = url.Substring(serverUrl.Length);
            }

            if (!url.StartsWith("http"))
            {
                if (url.StartsWith(web.ServerRelativeUrl))
                {
                    url = string.Format("{0}{1}", SPUrlPrefixConstants.Site, url.Substring(web.ServerRelativeUrl.Length));
                }
                else if (url.StartsWith(site.ServerRelativeUrl))
                {
                    url = string.Format("{0}{1}", SPUrlPrefixConstants.SiteCollection, url.Substring(site.ServerRelativeUrl.Length));
                }
            }

            // SPHelper.TryDisposeSite(site);

            return url;
        }
        /// <summary>
        /// Get prefixed url with "~site", the web prefix
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public static string GetWebPrefixedUrl(SPList list)
        {
            return string.Format("{0}/{1}", SPUrlPrefixConstants.Site, list.DefaultView.Url);
        }
        #endregion // UrlPrefix

        #region ParseUrlPrefix
        public static void ParseUrlPrefixInUrl(SPWeb web, ref string url, SPUrlType type)
        {
            string urlNoCase = url.ToLower();

            if (urlNoCase.StartsWith(SPUrlPrefixConstants.SiteCollection))
            {
                SPSite site = web.Site;
                {
                    url = string.Format("{0}{1}",
                        site.ServerRelativeUrl.TrimEnd('/'),
                        url.Substring(SPUrlPrefixConstants.SiteCollection.Length));
                }
                // SPHelper.TryDisposeSite(site);

            }
            else if (urlNoCase.StartsWith(SPUrlPrefixConstants.Site))
            {
                url = string.Format("{0}{1}",
                    web.ServerRelativeUrl.TrimEnd('/'),
                    url.Substring(SPUrlPrefixConstants.Site.Length));
            }

            if (type == SPUrlType.AbsoluteUrl && (url.Length == 0 || url[0] == '/'))
                url = string.Format("{0}{1}", SPHelper.GetAbsoluteUrlOfServer(web), url);
        }
        public static void ParseUrlPrefixesInText(SPWeb web, ref string text, SPUrlType type)
        {
            string prefix = (type == SPUrlType.AbsoluteUrl) ? SPHelper.GetAbsoluteUrlOfServer(web) : "";

            if (text.IndexOf(SPUrlPrefixConstants.SiteCollection, StringComparison.InvariantCultureIgnoreCase) > -1)
            {
                SPSite site = web.Site;
                {
                    string expanded = string.Format("{0}{1}", prefix, site.ServerRelativeUrl);
                    ReplacePrefix(ref text, SPUrlPrefixConstants.SiteCollection, expanded);
                }
                // SPHelper.TryDisposeSite(site);
            }

            if (text.IndexOf(SPUrlPrefixConstants.Site, StringComparison.InvariantCultureIgnoreCase) > -1)
            {
                string expanded = string.Format("{0}{1}", prefix, web.ServerRelativeUrl);
                ReplacePrefix(ref text, SPUrlPrefixConstants.Site, expanded);
            }
        }
        public static void ParseUrlPrefixesInText(SPWeb web, SPList list, ref string text, SPUrlType type)
        {
            string prefix = (type == SPUrlType.AbsoluteUrl) ? SPHelper.GetAbsoluteUrlOfServer(web) : "";

            if (text.IndexOf(SPUrlPrefixConstants.SiteCollection, StringComparison.InvariantCultureIgnoreCase) > -1)
            {
                SPSite site = web.Site;
                {
                    string expanded = string.Format("{0}{1}", prefix, site.ServerRelativeUrl);
                    ReplacePrefix(ref text, SPUrlPrefixConstants.SiteCollection, expanded);
                }
                // SPHelper.TryDisposeSite(site);
            }

            if (text.IndexOf(SPUrlPrefixConstants.Site, StringComparison.InvariantCultureIgnoreCase) > -1)
            {
                string expanded = string.Format("{0}{1}", prefix, web.ServerRelativeUrl);
                ReplacePrefix(ref text, SPUrlPrefixConstants.Site, expanded);
            }

            if (text.IndexOf(SPUrlPrefixConstants.List, StringComparison.InvariantCultureIgnoreCase) > -1)
            {
                string expanded = string.Format("{0}{1}", prefix, list.RootFolder.ServerRelativeUrl);
                ReplacePrefix(ref text, SPUrlPrefixConstants.List, expanded);
            }
        }
        private static void ReplacePrefix(ref string text, string prefix, string expanded)
        {
            expanded = expanded.TrimEnd('/');
            int idx = text.IndexOf(prefix, StringComparison.InvariantCultureIgnoreCase);
            while (idx > -1)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append(text.Remove(idx));
                sb.Append(expanded);
                sb.Append(text.Substring(idx + prefix.Length));
                text = sb.ToString();
                idx = text.IndexOf(prefix, idx + expanded.Length, StringComparison.InvariantCultureIgnoreCase);
            }
        }


        public static string ParseUrlPrefixInUrl(string prefixedUrl, string webUrl, string siteUrl)
        {
            StringBuilder builder;
            int length;
            if ((prefixedUrl != null) && (prefixedUrl.Length > 1))
            {
                if (prefixedUrl[0] != '~')
                {
                    return prefixedUrl;
                }
                builder = new StringBuilder(prefixedUrl.Length);
                length = -1;
                if (prefixedUrl.StartsWith(SPUtility.WebRelativeUrlPrefix, true, CultureInfo.InvariantCulture))
                {
                    if (webUrl != null)
                    {
                        builder.Append(webUrl);
                    }
                    else
                    {
                        builder.Append(SPContext.Current.Web.ServerRelativeUrl);
                    }
                    length = SPUtility.WebRelativeUrlPrefix.Length;
                }
                else
                {
                    if (!prefixedUrl.StartsWith(SPUtility.SiteRelativeUrlPrefix, true, CultureInfo.InvariantCulture))
                    {
                        return prefixedUrl;
                    }
                    if (siteUrl == null)
                    {
                        builder.Append(SPContext.Current.Site.ServerRelativeUrl);
                    }
                    else
                    {
                        builder.Append(siteUrl);
                    }
                    length = SPUtility.SiteRelativeUrlPrefix.Length;
                }
            }
            else
            {
                return prefixedUrl;
            }
            if ((builder.Length <= 0) || (builder[builder.Length - 1] != '/'))
            {
                builder.Append('/');
            }
            builder.Append(prefixedUrl.Substring(length));
            return builder.ToString();
        }
        #endregion // ParseUrlPrefix

        #region SPVariables
        public static void ParseSPVariablesInText(ref string text, SPWeb web, SPList list, SPListItem listItem)
        {
            if (web != null)
            {
                text = text.Replace("{SiteUrl}", web.ServerRelativeUrl.TrimEnd('/'));
                text = text.Replace("{SiteName}", web.Name);
                text = text.Replace("{SiteID}", web.ID.ToString("B"));
                text = text.Replace("{SiteId}", web.ID.ToString("B"));
                text = text.Replace("{SiteTitle}", web.Title);
            }
            if (list != null)
            {
                text = text.Replace("{ListUrl}", list.RootFolder.ServerRelativeUrl);
                text = text.Replace("{ListName}", list.RootFolder.Name);
                text = text.Replace("{ListID}", list.ID.ToString("B"));
                text = text.Replace("{ListId}", list.ID.ToString("B"));
                text = text.Replace("{ListTitle}", list.Title);
            }
            if (listItem != null)
            {
                if (web != null)
                {
                    text = text.Replace("{ItemUrl}", string.Format("{0}/{1}", web.Url, listItem.Url));
                }
                text = text.Replace("{ItemName}", listItem.Name);
                text = text.Replace("{ItemID}", listItem.ID.ToString());
                text = text.Replace("{ItemId}", listItem.ID.ToString());
                text = text.Replace("{ItemTitle}", listItem.Title);

                string recurrenceID = listItem.ID.ToString(CultureInfo.InvariantCulture);
                if (!string.IsNullOrEmpty(listItem.RecurrenceID))
                {
                    recurrenceID = listItem.RecurrenceID;
                }
                text = text.Replace("{RecurrenceId}", recurrenceID);
            }

            if (HttpContext.Current != null)
            {
                text = text.Replace("{Source}", HttpContext.Current.Request.Url.ToString());
            }
        }

        public static void ParseSPVariablesInText(ref string text)
        {
            ParseSPVariablesInText(ref text, SPContext.Current.Web, SPContext.Current.List, SPContext.Current.ListItem);
        }
        #endregion // SPVariables
    }
}
